<?php defined('SYSPATH') or die('No direct script access.');

/**
 * Created by PhpStorm.
 * Author: ls
 * Time: 2020/07/13 10:41
 * Desc: desc
 */
class Controller_Pc_Api_v2_Base extends Stourweb_Controller
{
    /*
     * 当前请求所属的api客户端信息
     */
    protected $client_info = null;
    /*
     * 当前请求内容体信息
     */
    protected $request_body = null;
    /*
    * 当前请求数据信息
    */
    protected $request_data = null;

    /**
     * 当前请求处理注入检测后的参数
     */
    protected $request_params = array();

    /**
     * 通过token获取会员id
     */
    protected $mid = 0;

    /**
     * 会员基础信息
     */
    protected $member_info = null;

    /**
     * 调试模式
     * @var bool
     */
    protected $debug = false;

    /**
     * 对应端显示
     * @return int
     */
    protected $platform_no;

    /**
     * 排除的接口地址，验证登录用
     * @var array
     */
    protected $eliminate_method = [
        'platforms/mp-weixin/login/login',
        'api/v2/system',
        'api/v2/common',
        'api/v2/member',
        'api/v2/dynamic',
        'api/v2/system/get_sys_configs'
    ];

    public function before()
    {
        header("Access-Control-Allow-Origin: *");
        header("Access-Control-Allow-Headers: *"); 
        set_exception_handler(array($this, "exception_handler"));
        set_error_handler(array($this, "error_handler"), 'E_ALL & ~E_DEPRECATED');

        parent::before();

        $this->middleware();
    }

    /**
     * 全局请求中间件
     * @return void
     */
    public function middleware()
    {
        //签名验证
        $this->verify_request();

        //必须是POST请求
        if ($this->request->method() != 'POST') {
            $response = $this->generate_response_data([], 101);
            $this->send_datagrams($this->client_info['id'], $response, $this->client_info['secret_key']);
        }

        // 请求参数处理
        $this->request_params = array_map(function ($item) {
            return Common::remove_xss($item);
        }, (array)$this->request_data);

        // 登录token处理验证
        $this->request_params['mid'] = 0;
        if (isset($this->request_params['token']) && $this->request_params['token']) {
            $check_token = Model_Api_V2_Pub::token_decode($this->request_params['token']);
            if ($check_token['status']) {
                $this->mid         = $check_token['mid'];
                $this->member_info = $check_token['info'];
                // 如果原有参数没有mid，设置mid
                $this->request_params['mid'] = $this->mid;
            }
        }

        $this->platform_no = $this->request_params['platform_no']?:1;

        $this->verify_login($this->request_params);

        // todo 客户端白名单验证
    }

    /**
     * @param $request_params
     * @return true|void
     * 请求登录验证
     */
    private function verify_login($request_params)
    {
        foreach ($this->eliminate_method as $method) {
            if(strpos($request_params['method'], $method) !== false) {
                return true;
            }
        }
        if($this->mid){
            return true;
        }
        $cfg_force_login = DB::select()->from('sysconfig')->where('varname','=','cfg_force_login')->execute()->get('value');
        if($cfg_force_login==1){
            $res = [
                'code' => -200,
                'status' => false,
                'msg' => '请先登录',
            ];
            $this->send_datagrams($this->client_info['id'], $res, $this->client_info['secret_key']);
        }
    }

    /**
     * 请求验证
     * @return void
     */
    private function verify_request()
    {
        $request_content = file_get_contents("php://input");          
        $analyse_result  = Model_Api_Envelope::analyse_datagrams($request_content);
        if ($analyse_result['success'] === false) {
            $this->send_datagrams($analyse_result['client']['id'], null, $analyse_result['client']['secret_key'],
                $analyse_result['success'], $analyse_result['message'], $analyse_result['message']);
        }
        $this->client_info  = $analyse_result['client'];
        $this->request_body = $analyse_result['body'];
        $this->request_data = $analyse_result['body'];
    }

    public function exception_handler($e)
    {
        // Get the exception information
        $type    = get_class($e);
        $code    = $e->getCode();
        $message = $e->getMessage();
        $file    = $e->getFile();
        $line    = $e->getLine();
        $trace   = $e->getTrace(); // Get the exception backtrace

        $msg = "errno:{$code}" . PHP_EOL;
        $msg .= "errstr:{$message}" . PHP_EOL;
        $msg .= "errfile:{$file}" . PHP_EOL;
        $msg .= "errline:{$line}" . PHP_EOL;
        // Display the exception text
        var_export($e);
        $this->send_datagrams($this->client_info['id'], null, $this->client_info['secret_key'], false, "API服务内部错误",
            $msg);
    }

    public function error_handler($errno, $errstr, $errfile, $errline)
    {
        throw new ErrorException($errstr, $errno, 0, $errfile, $errline);

        // Do not execute the PHP error handler
        return true;
    }

    /**
     * 记录交互日志
     * @param bool $success 是否成功
     * @param string $msg 错误信息
     * @param mixed $response 返回数据
     * @return void
     */
    protected function add_interop_log($success, $msg, $response)
    {
        $client_ip = Model_Api_Interop_Log::get_client_ip();
        $data      = array(
            'client_id' => $this->client_info['id'],
            'url' => $this->request->uri(),
            'request_params' => json_encode($this->request_body, 320),
            'response_data' => is_array($response) ? json_encode($response, 320) : '',
            'success' => ($success ? 1 : 0),
            'msg' => $msg,
            'remote_info' => "IP:{$client_ip}"
        );
        Model_Api_Interop_Log::add_info($data);
    }

    /**
     * 发送响应报文
     * @param $client_id
     * @param $content
     * @param $secret_key
     * @param $success
     * @param $message
     * @param $log_message
     * @param $is_abort
     * @return void
     */
    protected function send_datagrams($client_id, $content, $secret_key = "", $success = true, $message = "", $log_message = "", $is_abort = true)
    {
        // 记录交互日志
        $this->add_interop_log($success, $log_message, $content);

        if (!$content['code'] && $content) {
            $content = $this->generate_response_data($content);
        }
        $api_envelop = new Model_Api_Envelope($client_id, $content, $success, $message);
        $datagrams   = $api_envelop->generate_datagrams($secret_key, $this->debug);
        header("content-type:application/json");
        if ($is_abort) {
            exit($datagrams);
        } else {
            echo $datagrams;
        }
    }

    /**
     * 获取货币符号
     */
    public function action_symbol()
    {
        $this->send_datagrams($this->client_info['id'], array('symbol' => Currency_Tool::symbol()),
            $this->client_info['secret_key']);
    }

    /**
     * 判断是否为json
     * @param $params
     * @return bool
     * User: netman
     * Date: 2023/8/2 11:59
     */
    public function is_json($params)
    {
        json_decode($params);
        return (json_last_error() == JSON_ERROR_NONE);
    }

    /**
     * 生成统一返回内容
     * @param array $data
     * @param $code
     * @return array
     * User: netman
     * Date: 2023/9/5 16:56
     */
    public function generate_response_data(array $data, $code = 200)
    {
        $data['code'] = $code;
        if (!isset($data['status'])) {
            $data['status'] = true;
        }
        if (!$data['msg']) {
            $data['msg'] = 'success';
        }
        if (!$data['data']) {
            $data['data'] = [];
        }
        return $data;
    }
}